﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ServiceModel.DomainServices.Client.ApplicationServices;
using System.ServiceModel.DomainServices.Client;
using MyBet.Web;
using System.Collections.Generic;
using MyBet.Class;
using MyBet.Helpers;
using System.Windows.Media.Imaging;

namespace MyBet
{
	public partial class EventBet2 : UserControl
    {

        #region Attributes
        private bool _isLoaded = false;
        private bool _isEventsLoaded = false;
        private bool _isMatchsLoaded = false;
        private int _championshipId;
        private int _seasonId;
        private Dictionary<int, EventServiceReference.MatchObject> matchDictionnary;
        private int _currentEventId;
        private MatchsList _matchs;
        private DaysList _days;
        private EventServiceReference.EventObject _selectedEvent;
        private BackgroundWorker _GUIWorker;
        #endregion

        #region Events

        /// <summary>
        /// Event to indicate the list of match is loaded
        /// </summary>
        public delegate void MatchLoaded();
        public event MatchLoaded OnMatchLoaded;
        /// <summary>
        /// Event to indicate the list of match is loaded
        /// </summary>
        public delegate void MatchLoading();
        public event MatchLoading OnMatchLoading;

        #endregion

        //private delegate void UpdateSelectedEventDelegateHandler(EventGUI evt);
        //private UpdateSelectedEventDelegateHandler UpdateSelectedEventDelegate;

        #region Properties
        public MatchsList Matchs
        {
            get { return _matchs; }
            set { _matchs = value; }
        }

        /// <summary>
        /// Id de l'événement courant
        /// </summary>
        public int CurrentEventId
        {
            get { return _currentEventId; }
            set { _currentEventId = value; }
        }

        public BackgroundWorker GUIWorker
        {
            get { return _GUIWorker; }
            set { _GUIWorker = value; }
        } 

        public EventServiceReference.EventObject SelectedEvent
        {
            get { return _selectedEvent; }
            set { _selectedEvent = value; }
        }

        public bool IsLoaded
        {
            get { return _isLoaded; }
            set { _isLoaded = value; }
        }

        public int ChampionshipId
        {
            get { return _championshipId; }
            set { _championshipId = value; }
        }

        public DaysList Days
        {
            get { return _days; }
            set { _days = value; }
        }

        public int SeasonId
        {
            get { return _seasonId; }
            set { _seasonId = value; }
        }
        #endregion

        public EventBet2()
		{
			// Required to initialize variables
			InitializeComponent();
            SelectedEvent = null;
            EventNameText.Text = String.Empty;
            GUIWorker = new BackgroundWorker();
            GUIWorker.DoWork += new DoWorkEventHandler(GUIWorker_DoWork);
            //UpdateSelectedEventDelegate = new UpdateSelectedEventDelegateHandler(UpdateSelectedEvent);
            Days = new DaysList();
            Matchs = new MatchsList(StackRoot);
            Matchs.OnLoaded += new MatchsList.Loaded(Matchs_OnLoaded);
            matchDictionnary = new Dictionary<int, EventServiceReference.MatchObject>();
            // Mise à jour si modification de la journée courante
            EventsDataGrid.EventsList.SelectionChanged += new SelectionChangedEventHandler(EventsList_SelectionChanged);
		}

        void EventsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
                // Set busy indicator
                BusyControl.Visibility = Visibility.Visible;

                IsLoaded = false;
                _isMatchsLoaded = false;
                // Load matchs
                EventServiceReference.EventObject currentEvent = EventsDataGrid.EventsList.SelectedItem as EventServiceReference.EventObject;
                if (currentEvent != null)
                {
                    OnMatchLoading();
                    SelectedEvent = currentEvent;
                    Matchs.Load(currentEvent);
                }
                if ((App.CurrentUser != null) && (currentEvent != null))
                {
                    EventServiceReference.GetEventScoreClient svc2 = new EventServiceReference.GetEventScoreClient();
                    svc2.GetEventInformationCompleted += new EventHandler<EventServiceReference.GetEventInformationCompletedEventArgs>(svc_GetScoreCompleted);
                    svc2.GetEventInformationAsync(App.CurrentUser.UserId, currentEvent._eventId, App.CurrentUser.CustomContestId);
                    EventNameText.Text =EventHelper.GetEventName(currentEvent);
                }
        }

        /// <summary>
        /// Function to update selected item in event list
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void GUIWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //if (SelectedEvent != null)
            //{
            //    object[] parameters = new object[1];
            //    parameters[0]=SelectedEvent;
            //    this.Dispatcher.BeginInvoke(new UpdateSelectedEventDelegateHandler(UpdateSelectedEvent), parameters);
            //}
        }

        //void InternalEventList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        //{
        //    // Set busy indicator
        //    BusyControl.Visibility = Visibility.Visible;
            
        //    IsLoaded = false;
        //    _isMatchsLoaded = false;
        //    // Load matchs
        //    EventGUI currentEvent = EventsList.InternalEventList.SelectedItem as EventGUI;
        //    if (currentEvent != null)
        //    {
        //        OnMatchLoading();
        //        SelectedEvent = currentEvent;
        //        Matchs.Load(currentEvent);
        //    }
        //    if ((App.CurrentUser != null) && (currentEvent!=null))
        //    {

        //        //EventServiceReference.GetEventScoreClient svc = new EventServiceReference.GetEventScoreClient();
        //        //svc.GetBestScoreCompleted += new EventHandler<EventServiceReference.GetBestScoreCompletedEventArgs>(svc_GetBestScoreCompleted);
        //        //svc.GetBestScoreAsync(currentEvent.GetEvent._eventId, App.CurrentUser.CustomContestId);

        //        EventServiceReference.GetEventScoreClient svc2 = new EventServiceReference.GetEventScoreClient();
        //        svc2.GetEventInformationCompleted += new EventHandler<EventServiceReference.GetEventInformationCompletedEventArgs>(svc_GetScoreCompleted);
        //        svc2.GetEventInformationAsync(App.CurrentUser.UserId, currentEvent.GetEvent._eventId,App.CurrentUser.CustomContestId);
        //        EventNameText.Text = currentEvent.ToString();
        //    }
            
        //}

        void svc_GetScoreCompleted(object sender, EventServiceReference.GetEventInformationCompletedEventArgs e)
        {
            // Mise à jour du meilleur score
            
            if (e.Result.userScore != -1)
            {
                if (e.Result.bestScore != -1)
                {
                    BestScoreText.Text = String.Format("{0} pt / {1} pt", e.Result.userScore, e.Result.bestScore);
                }
                else
                {
                    BestScoreText.Text = String.Format("{0} pt / ?", e.Result.userScore);
                }
            }
            else
            {
                if (e.Result.bestScore != -1)
                {
                    BestScoreText.Text = String.Format("- pt / {0} pt", e.Result.bestScore);
                }
                else
                {
                    BestScoreText.Text = "- pt";
                }
            }

            // Mise à jour de la date de pari
            UpdateLastBetUpdateDate(e.Result.lastUpdate);
        }

        /// <summary>
        /// Mise à jour du libellé avec la date de derniere mise à jour du pari
        /// </summary>
        /// <param name="updateDate"></param>
        protected void UpdateLastBetUpdateDate(DateTime updateDate)
        {
            if (updateDate != DateTime.MinValue)
            {
                LastUpdateTxt.Text = String.Format(LangHelper.GetString("LastBetUpdateLabel"), UserTimezone.FromUTC(updateDate));
                LastUpdateImage.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                LastUpdateTxt.Text = String.Empty;
                LastUpdateImage.Visibility = System.Windows.Visibility.Collapsed;
            }
        }

        public void Update()
        {
            if ((App.CurrentUser != null) && (App.CurrentUser.CurrentContestChampionshipId!=0))
            {
                // Mise à jour de la liste des matchs
                OnMatchLoading();
                // Set championship id from current contest
                ChampionshipId = App.CurrentUser.CurrentContestChampionshipId;
                // Set season id from current contest
                SeasonId = App.CurrentUser.CurrentContestSeasonId;
                // Load list of championship days
                //var queryChampionships = App.BetContext.GetEventsFromContestQuery(ChampionshipId, SeasonId);
                //App.BetContext.Load(queryChampionships, championshipDaysCombobox_Loaded, null);
                EventServiceReference.GetEventScoreClient eventSvc = new EventServiceReference.GetEventScoreClient();
                eventSvc.GetEventListCompleted += new EventHandler<EventServiceReference.GetEventListCompletedEventArgs>(eventSvc_GetEventListCompleted);
                eventSvc.GetEventListAsync(App.CurrentUser.CustomContestId);
            }          
        }

        void eventSvc_GetEventListCompleted(object sender, EventServiceReference.GetEventListCompletedEventArgs e)
        {
            matchDictionnary.Clear();
            Days.EventsDictionnary.Clear();
            
            foreach (EventServiceReference.EventObject newEvent in e.Result)
            {
                if (newEvent._eventId == CurrentEventId)
                {
                    SelectedEvent = newEvent;
                }
                Days.EventsDictionnary.Add(newEvent._eventId, newEvent);
            }


            CurrentEventId = Days.GetCurrentEventId();
            App.CurrentEventId = CurrentEventId;

            if (Days.EventsDictionnary.ContainsKey(CurrentEventId))
            {
                Matchs.Event = Days.EventsDictionnary[CurrentEventId];
            }

            EventsDataGrid.LoadEvents(CurrentEventId, e.Result);

            lock (this)
            {
                _isEventsLoaded = true;
                IsLoaded = _isEventsLoaded && _isMatchsLoaded;
            }

            // Reload matchs
            Matchs.Reload();
        }

        /// <summary>
        /// List of matchs is loaded
        /// </summary>
        void Matchs_OnLoaded()
        {
            lock (this)
            {
                _isMatchsLoaded = true;
                IsLoaded = _isEventsLoaded && _isMatchsLoaded;
            }
            // Update deadline Information
            UpdateDeadline();

            // Fin de mise à jour des matchs
            OnMatchLoaded();
        }

        private void UpdateDeadline()
        { 
            EventServiceReference.EventObject evt = EventsDataGrid.EventsList.SelectedItem as EventServiceReference.EventObject;
            BitmapImage bmi;
            if (evt == null)
            {
                return;
            }

            switch (Matchs.Status)
            {
                case DaysList.DayStatus.NotStarted:
                    // display start date
                    bmi = new BitmapImage(new Uri(@"information_32.png", UriKind.Relative));
                    StatusImage.Source = bmi;
                    StatusImage.Visibility = System.Windows.Visibility.Visible;
                    DeadlineTxt.Text = String.Format(LangHelper.GetString("CloseBetDate"), UserTimezone.FromUTC(evt._closeDate));
                    BetButton.Visibility = Visibility.Visible;
                    BestScoreImage.Visibility = Visibility.Collapsed;
                    BestScoreText.Visibility = Visibility.Collapsed;
                    break;
                case DaysList.DayStatus.Finished:
                    // display end date
                    bmi = new BitmapImage(new Uri(@"forbidden_32.png", UriKind.Relative));
                    StatusImage.Source = bmi;
                    StatusImage.Visibility = System.Windows.Visibility.Visible;
                    DeadlineTxt.Text = String.Format(LangHelper.GetString("CloseBet"), UserTimezone.FromUTC(evt._closeDate));
                    BetButton.Visibility = Visibility.Collapsed;
                    BestScoreImage.Visibility = Visibility.Visible;
                    BestScoreText.Visibility = Visibility.Visible;
                    break;
                case DaysList.DayStatus.Bet:
                    // display close date
                    bmi = new BitmapImage(new Uri(@"warning_32.png", UriKind.Relative));
                    StatusImage.Source = bmi;
                    StatusImage.Visibility = System.Windows.Visibility.Visible;
                    DeadlineTxt.Text = String.Format(LangHelper.GetString("CloseBetDate"), UserTimezone.FromUTC(evt._closeDate));
                    BetButton.Visibility = Visibility.Visible;
                    BestScoreImage.Visibility = Visibility.Collapsed;
                    BestScoreText.Visibility = Visibility.Collapsed;
                    break;
                default:
                    break;
            }
                
        }

        /// <summary>
        /// Change culture
        /// </summary>
        public void UpdateCulture()
        {
            List<EventGUI> tmpDaysList = new List<EventGUI>();
            UpdateDeadline();
            BetButton.Content = LangHelper.GetString("BetButton");
            if (SelectedEvent != null)
            {
                EventNameText.Text = EventHelper.GetEventName(SelectedEvent);
            }

            // TODO : Gestion de la culture
            // EventsList.UpdateCulture();
        }

        private void BetButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            bool bRet = true;
            List<int> matchId = new List<int>();
            List<int> scoreHome = new List<int>();
            List<int> scoreAway = new List<int>();

            BusyPopup.IsBusy = true;
            BusyPopup.BusyContent = Helpers.LangHelper.GetString("WaitingBetValidation");

        	// Validate user is authenticated
            if (App.CurrentUser == null)
            {
                Error errDlg = new Error(LangHelper.GetString("ErrorBetTitle"), LangHelper.GetString("ErrorUserNotAuthenticated"), Error.ErrorType.CriticalError);
                errDlg.Show();
                BusyPopup.IsBusy = false;
                return;              
            }
            // Validate all scores are filled
            foreach (MatchControl mc in StackRoot.Children)
            {
                
                bRet = bRet && (mc.TeamHomeScore.SelectedIndex != -1) && (mc.TeamAwayScore.SelectedIndex != -1);
                if (bRet)
                {
                    matchId.Add(mc.MatchId);
                    scoreHome.Add(mc.TeamHomeScore.SelectedIndex);
                    scoreAway.Add(mc.TeamAwayScore.SelectedIndex);
                }
            }
            if (!bRet)
            {
                Error errDlg = new Error(LangHelper.GetString("ErrorBetTitle"), LangHelper.GetString("ErrorScoreEmpty"), Error.ErrorType.CriticalError);
                errDlg.Show();
                BusyPopup.IsBusy = false;
                return;
            }


            // Validate bet
            //App.BetContext.SetBet(App.CurrentUser.Email, ChampionshipId, CurrentDayNumber, SeasonId, matchId, scoreHome, scoreAway, BetValidated, null);

            // Call prediction service to get prediction for all matchs of the current event
            System.Collections.ObjectModel.ObservableCollection<int> predictionHome = new System.Collections.ObjectModel.ObservableCollection<int>();
            System.Collections.ObjectModel.ObservableCollection<int> predictionAway = new System.Collections.ObjectModel.ObservableCollection<int>();
            System.Collections.ObjectModel.ObservableCollection<int> predictionMatchId = new System.Collections.ObjectModel.ObservableCollection<int>();
            foreach (int s1 in scoreHome)
            {
                predictionHome.Add(s1);
            }
            foreach (int s2 in scoreAway)
            {
                predictionAway.Add(s2);
            }
            foreach (int s3 in matchId)
            {
                predictionMatchId.Add(s3);
            }

            PredictionServiceReference.PredictionServiceClient predictionSvc = new PredictionServiceReference.PredictionServiceClient();
            predictionSvc.SetPredictionCompleted += new EventHandler<PredictionServiceReference.SetPredictionCompletedEventArgs>(predictionSvc_SetPredictionCompleted);
            predictionSvc.SetPredictionAsync(App.CurrentUser.UserId, SelectedEvent._eventId, predictionMatchId, predictionHome, predictionAway,EventNameText.Text,true);
        }

        void predictionSvc_SetPredictionCompleted(object sender, PredictionServiceReference.SetPredictionCompletedEventArgs e)
        {
            BusyPopup.IsBusy = false;
            if (e.myFault != null)
            {
                Error dlg = new Error("", String.Format(LangHelper.GetString("PredictionFailure2"), e.myFault.Message), Error.ErrorType.CriticalError);
                dlg.Show();                
            }
            else if (e.Result == PredictionServiceReference.BetObject.PredictionValidationStatus.Success)
            {
                DateTime betDate=DateTime.UtcNow;
                Error dlg = new Error("", LangHelper.GetString("BetSaved"), Error.ErrorType.Info);
                dlg.Show();
                UpdateLastBetUpdateDate(betDate);
            }
            else if (e.Result == PredictionServiceReference.BetObject.PredictionValidationStatus.DateExpired)
            {
                Error dlg = new Error("", LangHelper.GetString("PredictionDateExpired"), Error.ErrorType.CriticalError);
                dlg.Show();                
            }
            else
            {
                Error dlg = new Error("", LangHelper.GetString("PredictionFailure"), Error.ErrorType.CriticalError);
                dlg.Show();
            }
        }

        private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            if (!GUIWorker.IsBusy)
            {
                // Update GUI asynchronously
                this.GUIWorker.RunWorkerAsync();
            }
        }

	}
}